package zhuyun.code.launcheractivity.model

import android.text.TextUtils
import com.google.gson.GsonBuilder
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.observers.DisposableObserver
import io.reactivex.schedulers.Schedulers
import okhttp3.*
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import zhuyun.code.launcheractivity.utils.EncryUrl
import zhuyun.code.launcheractivity.utils.GZIPUtils
import zhuyun.code.launcheractivity.utils.SPUtils
import zhuyun.code.launcheractivity.utils.TimeUtils
import java.util.concurrent.TimeUnit

/**
 * @author: Administrator
 * @date: 2021/11/17
 */
object HttpMethods {
    private const val DEFAULT_CONNECT_TIMEOUT = 3000L
    private const val DEFAULT_WRITE_TIMEOUT = 30L
    private const val DEFAULT_READ_TIMEOUT = 30L
    private const val RETRY_COUNT = 0L
    private val okHttpBuilder = OkHttpClient.Builder()
    private lateinit var retrofit:Retrofit
    private lateinit var retrofitChat:Retrofit
    lateinit var httpApi: HttpApi
    lateinit var httpApiChat: HttpApi
    val instance by lazy {
        val headerInterceptor = Interceptor { it ->
            val originalRequest = it.request()
            val random = (Math.random()*10000).toLong()
            val time = TimeUtils.getTime()
//            val random = 4536
//            val time = "1638162242416"
            val requestBuilder = originalRequest.newBuilder()
                .addHeader("Accept-Encoding","gzip")
                .addHeader("Accept","application/json")
                .addHeader("Content-Type","application/json; charset=utf-8")
                .addHeader("Nonce","$random")
                .addHeader("Timestamp", time)
                .method(originalRequest.method(),originalRequest.body())
            val map = HashMap<String,String>()
            map["Nonce"]="$random"
            map["Timestamp"]=time
            val s = it.request().url().encodedQuery()
            s?.let {
                if(s.isNotEmpty()){
                    val split = s.split("&")
                    for(aSplit in split){
                        val aSplitResult = aSplit.split("=")
                        if(aSplitResult.size == 2){
                            map[aSplitResult[0]] = aSplitResult[1]
                        } else {
                            map[aSplitResult[0]] = ""
                        }
                    }
                }
            }
            if(headerMap != null){
                val iterator = headerMap!!.entries!!.iterator()
                while(iterator.hasNext()){
                    val entry = iterator.next()
                    map[entry.key] = entry.value
                }
                headerMap!!.clear()
                headerMap == null
            }
            val token = SPUtils.getUserString(Constants.TOKEN,"")
            //val token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiIxMzc1OCIsIlByb2plY3QiOiJ3ZWJhcGkiLCJuYmYiOjE2Mzc0ODIyNjMsImV4cCI6MTYzODc3ODI2MywiaWF0IjoxNjM3NDgyMjYzLCJpc3MiOiJzdGFyLmluZXQ4ODg4LmNvbSIsImF1ZCI6InN0YXIuaW5ldDg4ODguY29tIn0.56w4ThKNnHSGQ-TR2jdF-NSkYgwM7PkB5HBp_tq5A6M"
            if(!TextUtils.isEmpty(token)){
                map["Authorization"] = token!!
                requestBuilder.addHeader("Authorization",token)
            }
            requestBuilder.addHeader("Sign",EncryUrl.getEncryptionParams(map))
            requestBuilder.addHeader("Accept-Language","zh-CN")
            val request = requestBuilder.build()
            it.proceed(request)
        }

        val networkInterceptor = Interceptor {
            val request = it.request()
            val response = it.proceed(request)
            if(response.code() == 200){
                val mediaType = response.body()!!.contentType()
                var data = response.body()!!.bytes()
                if(GZIPUtils.isGzip(response.headers())){
                    data = GZIPUtils.uncompress(data)
                }
                response.newBuilder().body(ResponseBody.create(mediaType,data)).build()
            } else {
                response
            }
        }
        okHttpBuilder.addInterceptor(networkInterceptor)
        okHttpBuilder.addInterceptor(headerInterceptor)

        okHttpBuilder.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS)
        okHttpBuilder.readTimeout(DEFAULT_WRITE_TIMEOUT,TimeUnit.SECONDS)
        okHttpBuilder.writeTimeout(DEFAULT_READ_TIMEOUT,TimeUnit.SECONDS)
        okHttpBuilder.retryOnConnectionFailure(true)
        retrofit = Retrofit.Builder().client(okHttpBuilder.build()).addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).baseUrl(Constants.BASE_URL).build()
        retrofitChat = Retrofit.Builder().client(okHttpBuilder.build()).addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).baseUrl(Constants.CHAT_BASE_URL).build()
        httpApi = retrofit.create(HttpApi::class.java)
        httpApiChat = retrofitChat.create(HttpApi::class.java)
        this
    }

    private var headerMap:MutableMap<String,String>? = null

    fun withHeader(headerMap:MutableMap<String,String>?):HttpMethods{
        this.headerMap = headerMap
        return this
    }

    fun<T> toSubscribe(observable: Observable<T>, observer:DisposableObserver<T>){
        observable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .retry(RETRY_COUNT)
            .subscribe(observer)
    }
}